﻿using MyCompanyName.AbpZeroTemplate.Request;
using MyCompanyName.AbpZeroTemplate.Request.Handler;
using MyCompanyName.AbpZeroTemplate.Response;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;

namespace MyCompanyName.AbpZeroTemplate.Gantt
{
    public class GanttAppService : MyCompanyName.AbpZeroTemplate.Gantt.IGanttAppService
    {
        public const string dateFormat = "yyyy-MM-dd\\THH:mm:ss";

        GanttManager gantt;

        public GanttAppService(GanttManager ganttManager)
        {
            gantt = ganttManager;
        }

        public void GetProcess(int taskId)
        {
            var res = gantt.getSchedules(taskId).Select(x => new
            {
                Id = x.Id,
                CreateOn = x.CreateOn.ToString("yyyy-MM-dd"),
                CreateBy = x.CreateBy,
                Value = x.Value,
                Remark = x.Remark
            }).ToList();
        }

        public void SaveProcess(int Percent, string Remark, int TaskId)
        {
            gantt.saveProcess(Percent, Remark, TaskId);
        }


        public void GetFiles(int taskId)
        {
            var res = gantt.getAttachments(taskId).Select(x => new
            {
                Id = x.Id,
                CreateOn = x.CreateOn.ToString("yyyy-MM-dd"),
                CreateBy = x.CreateBy,
                Name = x.Name,
                Extension = x.Extension
            });
        }


        public void Download(int attId)
        {
            var att = gantt.getAttachment(attId);
            //  return File(att.Value, "application/octet-stream", att.Name);
        }


        public void SaveAttachment(HttpPostedFileBase file, int TaskId)
        {
            gantt.saveAttachment(file, TaskId);
        }

        //public ActionResult GetAllTasks()
        //{
        //    var gantt = new Gantt.EntityFramework.Gantt();
        //    var tasks = gantt.getAllTasks().Select(x => new // PM.Web.Models.TaskInfo
        //    {
        //        Id = x.Id,
        //        ParentId = x.parentIdRaw.GetValueOrDefault(),
        //        Title = x.Name,
        //        Describe = x.Note,
        //        Deliverydate = x.EndDate.ToString(),
        //        Progress = x.PercentDone.GetValueOrDefault(),
        //        Participants = x.Assignments.ToList().Select(q => new
        //        {
        //            Id = q.Resource.Name,
        //            Name = q.Resource.Name
        //        }),
        //        //Flags = x.Color,
        //        Subtasks = x.ChildrenRaw.Select(q => new { Id = q.Id, State = parse(q.PercentDone) })
        //    }).ToList();
        //    var res = new { records = tasks };
        //    return Json(res, JsonRequestBehavior.AllowGet);
        //}

        public void GetTask(int TaskId)
        {
            var t = gantt.getTask(TaskId);

            //return Json(new
            //{
            //    success = true,
            //    data = new
            //    {
            //        Title = t.Name,
            //        PercentDone = t.PercentDone,
            //        StartDate = t.StartDate.ToString(),
            //        EndDate = t.EndDate.ToString(),
            //        Participants = string.Join(",", t.Assignments.ToList().Select(q => q.Resource.Name)),
            //        Note = t.Note,
            //        CreateOn = DateTime.Now.ToString("yyyy-MM-dd"),
            //        CreateBy = "debug"
            //    }
            //});
        }

        //private PM.Web.Models.TaskStatus parse(int? done)
        //{
        //    if (!done.HasValue)
        //    {
        //        return PM.Web.Models.TaskStatus.未开始;
        //    }
        //    if (done.Value == 0)
        //    {
        //        return PM.Web.Models.TaskStatus.未开始;
        //    }
        //    if (done.Value == 100)
        //    {
        //        return PM.Web.Models.TaskStatus.已完成;
        //    }
        //    return PM.Web.Models.TaskStatus.进行中;
        //}

        /// <summary>
        /// Helper method to get POST request body.
        /// </summary>
        ///// <returns>POST request body.</returns>        
        private string getPostBody()
        {
            Stream req = HttpContext.Current.Request.InputStream;
            req.Seek(0, System.IO.SeekOrigin.Begin);
            return new StreamReader(req).ReadToEnd();
        }


        public void GetInit()
        {
            gantt.setOption("revision", "1");
            gantt.setOption("projectCalendar", "1");
            gantt.InitTask(new Task()
            {
                parentId = null,
                Name = "New Task",
                StartDate = DateTime.Now,
                EndDate = DateTime.Now.AddDays(10),
                Duration = 10,
                DurationUnit = "d",
                PercentDone = 0,
                index = 0,
                expanded = false,
                ManuallyScheduled = false,
                Draggable = true,
                Resizable = true,
                Rollup = false,
                ShowInTimeline = false,
                PhantomId = "Gnt.examples.advanced.model.Task-1"
            });
        }


        /// <summary>
        /// Load request handler.
        /// </summary>
        /// <returns>JSON encoded response.</returns>
        // [System.Web.Mvc.HttpGet]
        public string GetGannts([FromUri] string q)
        {
            GanttLoadRequest loadRequest = null;
            ulong? requestId = null;
            // decode request object
            try
            {
                loadRequest = JsonConvert.DeserializeObject<GanttLoadRequest>(q);
            }
            catch (Exception)
            {
                throw new Exception("Invalid load JSON");
            }

            // get request identifier
            requestId = loadRequest.requestId;

            // initialize response object
            var loadResponse = new GanttLoadResponse(requestId);

            // if a corresponding store is requested then add it to the response object

            if (loadRequest.calendars != null) loadResponse.setCalendars(gantt.getCalendars(), 1);
            if (loadRequest.assignments != null) loadResponse.setAssignments(gantt.getAssignments());
            if (loadRequest.tasks != null) loadResponse.setTasks(gantt.getTasks());
            if (loadRequest.resources != null) loadResponse.setResources(gantt.getResources());
            if (loadRequest.dependencies != null) loadResponse.setDependencies(gantt.getDependencies());

            // put current server revision to the response
            loadResponse.revision = gantt.getRevision();

            // just in case we make any changes during load request processing

            return JsonConvert.SerializeObject(loadResponse);
        }

        protected SyncStoreResponse AddModifiedRows(string table, SyncStoreResponse resp)
        {
            if (gantt.HasUpdatedRows(table))
            {
                if (resp == null) resp = new SyncStoreResponse();
                var rows = gantt.GetUpdatedRows(table);
                resp.rows = resp.rows != null ? resp.rows.Concat(rows).ToList() : rows;
            }
            if (gantt.HasRemovedRows(table))
            {
                if (resp == null) resp = new SyncStoreResponse();
                var removed = gantt.GetRemovedRows(table);
                resp.removed = resp.removed != null ? resp.removed.Concat(removed).ToList() : removed;
            }
            return resp;
        }

        /// <summary>
        /// 同步响应处理程序.
        /// </summary>
        /// <returns>JSON encoded response.</returns>
        // [System.Web.Mvc.HttpPost]
        public string Sync()
        {
            ulong? requestId = null;
            GanttSyncRequest syncRequest = null;

            string json = getPostBody();

            // decode request object
            try
            {
                syncRequest = JsonConvert.DeserializeObject<GanttSyncRequest>(json, new Newtonsoft.Json.Converters.IsoDateTimeConverter { DateTimeFormat = dateFormat });
            }
            catch (Exception)
            {
                throw new Exception("Invalid sync JSON");
            }

            // initialize phantom to real Id maps
            gantt.InitRowsHolders();

            // get request identifier
            requestId = syncRequest.requestId;

            // initialize response object
            var syncResponse = new GanttSyncResponse(requestId);

            // Here we reject client's changes if we suspect that they are out-dated
            // considering difference between server and client revisions.
            // You can get rid of this call if you don't need such behavior.
            gantt.checkRevision(syncRequest.revision);

            // 如果相应的修改数据存储提供了我们处理它们

            // 首先让我们处理添加和更新记录

            CalendarSyncHandler calendarHandler = null;
            if (syncRequest.calendars != null)
            {
                calendarHandler = new CalendarSyncHandler(gantt, dateFormat);
                syncResponse.calendars = calendarHandler.Handle(syncRequest.calendars, CalendarSyncHandler.Rows.AddedAndUpdated);
            }
            ResourceSyncHandler resourcesHandler = null;
            if (syncRequest.resources != null)
            {
                resourcesHandler = new ResourceSyncHandler(gantt);
                syncResponse.resources = resourcesHandler.Handle(syncRequest.resources, ResourceSyncHandler.Rows.AddedAndUpdated);
            }
            TaskSyncHandler taskHandler = null;
            if (syncRequest.tasks != null)
            {
                taskHandler = new TaskSyncHandler(gantt, dateFormat);
                syncResponse.tasks = taskHandler.Handle(syncRequest.tasks, TaskSyncHandler.Rows.AddedAndUpdated);
            }
            AssignmentSyncHandler assignmentHandler = null;
            if (syncRequest.assignments != null)
            {
                assignmentHandler = new AssignmentSyncHandler(gantt);
                syncResponse.assignments = assignmentHandler.Handle(syncRequest.assignments, AssignmentSyncHandler.Rows.AddedAndUpdated);
            }
            DependencySyncHandler dependencyHandler = null;
            if (syncRequest.dependencies != null)
            {
                dependencyHandler = new DependencySyncHandler(gantt);
                syncResponse.dependencies = dependencyHandler.Handle(syncRequest.dependencies, DependencySyncHandler.Rows.AddedAndUpdated);
            }

            // then let's process records removals

            if (syncRequest.dependencies != null)
                syncResponse.dependencies = dependencyHandler.HandleRemoved(syncRequest.dependencies, syncResponse.dependencies);

            if (syncRequest.assignments != null)
                syncResponse.assignments = assignmentHandler.HandleRemoved(syncRequest.assignments, syncResponse.assignments);

            if (syncRequest.tasks != null)
                syncResponse.tasks = taskHandler.HandleRemoved(syncRequest.tasks, syncResponse.tasks);

            if (syncRequest.resources != null)
                syncResponse.resources = resourcesHandler.HandleRemoved(syncRequest.resources, syncResponse.resources);

            if (syncRequest.calendars != null)
                syncResponse.calendars = calendarHandler.HandleRemoved(syncRequest.calendars, syncResponse.calendars);

            // we also return implicit modifications made by server
            // (implicit records updates/removals caused by data references)

            syncResponse.calendars = AddModifiedRows("calendars", syncResponse.calendars);
            syncResponse.tasks = AddModifiedRows("tasks", syncResponse.tasks);
            syncResponse.resources = AddModifiedRows("resources", syncResponse.resources);
            syncResponse.assignments = AddModifiedRows("assignments", syncResponse.assignments);
            syncResponse.dependencies = AddModifiedRows("dependencies", syncResponse.dependencies);

            // put current server revision to the response
            syncResponse.revision = gantt.getRevision();


            return JsonConvert.SerializeObject(syncResponse);
        }

    }
}
